package com.sofwin.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sofwin.Constants;
import com.sofwin.annotation.Log;
import com.sofwin.annotation.OperatorType;
import com.sofwin.pojo.SysOperatorLog;
import com.sofwin.pojo.SysUser;
import com.sofwin.system.service.OperatorService;
import com.sofwin.system.service.UserService;
import com.sofwin.util.DateUtil;
import jdk.nashorn.internal.runtime.regexp.JoniRegExp;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @packageName: com.sofwin.aspect
 * @user: andyliu
 * @date: 2021/12/21 9:40
 * @email 115176513@qq.com
 * @description: TODO
 */
@Component
@Aspect
public class LogAspect {
    @Autowired
    private OperatorService operatorService;
    @Autowired
    private UserService userService;

    // 通过切入点查找指定的注解
    @Pointcut("@annotation(com.sofwin.annotation.Log)")
    public void a(){

    }
    // 后置增强
    @AfterReturning(pointcut = "a()",returning = "result")
    public void AfterReturning(JoinPoint joinPoint,Object result) throws NoSuchMethodException, JsonProcessingException {
        handler(joinPoint,result,null);
    }
    @AfterThrowing(pointcut = "a()",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Throwable ex) throws JsonProcessingException, NoSuchMethodException {
        handler(joinPoint,null,ex);
    }

    public void handler(JoinPoint joinPoint,Object result,Throwable ex) throws JsonProcessingException, NoSuchMethodException {
        // 获取戳，包含了反射的相关信息，修饰符、类型等
        Signature signature = joinPoint.getSignature();
        // 获取目标类的类对象
        Class<?> clazz = joinPoint.getTarget().getClass();
        // 获取当前方法的方法名
        String name = signature.getName();
        System.out.println(name);
        // 构建方法参数的类对象数组
        Class[] parameters=new Class[joinPoint.getArgs().length];
        for(int i=0;i<joinPoint.getArgs().length;i++){
            parameters[i]=joinPoint.getArgs()[i].getClass();
        }
        // 获取当前方法的类对象
        Method method= clazz.getMethod( name,parameters);
        // 获取当前方法上的指定注解对象
        Log log = method.getAnnotation(Log.class);
        String moduleName = log.moduleName();
        OperatorType operatrorType = log.operatorType();
        System.out.println(moduleName);
        Object[] args = joinPoint.getArgs();
        // jackson中用于json序列化和反序列化  JSONObject
        ObjectMapper objectMapper = new ObjectMapper();
        // 普通java类中获取request对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 获取请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        // 将对象转为json格式的字符串
        String paramStr = objectMapper.writeValueAsString(parameterMap);
        String resultStr = objectMapper.writeValueAsString(result);
        System.out.println("paramStr:"+paramStr);
        System.out.println("resultStr:"+resultStr);
        //当前操作用户
        Subject subject = SecurityUtils.getSubject();//
        String loginName = subject.getPrincipal().toString();//获取用户名
        SysUser user = new SysUser();
        user.setLoginAccount(loginName);
        user = userService.checkLogin(user);
        // 获取远程主机名称
        String remoteHost = request.getRemoteHost();
        // 获取请求方式(get post)
        String requestMethod = request.getMethod();
        // 获取请求uri
        String requestURI = request.getRequestURI();
        // 获取当前方法的方法名
        String controllerMethod = method.getName();
        // 状态正常
        SysOperatorLog operatorLog = new SysOperatorLog();
        operatorLog.setHost(remoteHost);
        operatorLog.setModule(moduleName);
        operatorLog.setOperatorAddr(remoteHost);
        operatorLog.setOperatorDate(DateUtil.now());
        operatorLog.setUserId(user.getId());
        operatorLog.setType(String.valueOf(operatrorType));
        if(ex==null){
            // 正常
            operatorLog.setStatus(0);
        }else{
            // 失败
            operatorLog.setStatus(1);
        }
        operatorService.saveOrUpdate(operatorLog);
    }
}
